/*+***********************************************************************************
 Filename: 06_mcu02_sparrowrv_01\src\top.v
 Description: porting MCU based on SparrowRV Core from TangPrimer20kDock
   to tangnano9k.
   a mcu framework with 32k rom, 16k ram. 
   JTAG access rom, ram and peripheral through bus arbiter.
   Core access rom, access ram and peripheral through bus arbiter.

 Modification:
   2024.06.10 Creation   H.Zheng
           Porting from C01_mcu_sparrowrvcore


Copyright (C) 2024  Zheng Hui (hzheng@gzhu.edu.cn)

License: MulanPSL-2.0

***********************************************************************************-*/

module top
(
    input wire [1:0] button,
    input wire sys_clk,
    output wire [5:0] led,
    input wire uart0_rxd,
    output wire uart0_txd,
    input wire jtag_TCK,
    input wire jtag_TMS,
    input wire jtag_TDI,
    output wire jtag_TDO
);
    //PLL
    wire clk_108MHz;
    Gowin_rPLL m_pll(
        .clkout(clk_108MHz), //output clkout
        .clkin(sys_clk) //input clkin
    );

    //
    wire reset_n = button[1];
    wire jtag_reset_n = button[0];

    //core clk
    reg [26:0] counter;

    always @(posedge clk_108MHz) begin
        counter <= counter + 1'b1;
    end

//    wire core_clk = counter[0]; //54MHz  //not work
//    wire core_clk = counter[1]; //27MHz
//    wire core_clk = counter[3]; //6.25MHz
    wire core_clk = counter[2]; //13.5MHz
//    wire core_clk = counter[26]; //1Hz

//
    //jtag clk
    reg [5:0] jtagclk_counter;
    reg clk_1MHz;

    always @(posedge clk_108MHz) begin
        if (jtagclk_counter >=6'd53) begin
            jtagclk_counter <= 0;
            clk_1MHz <= ~clk_1MHz;
        end
        else begin
            jtagclk_counter <= jtagclk_counter + 1'b1;
        end
    end

  //jtag port
  wire jtag_halt_req_o;
  wire jtag_reset_req_o;
  wire[4:0] jtag_reg_addr_o;
  wire[31:0] jtag_reg_data_o;
  wire jtag_reg_we_o;
  wire[31:0] jtag_reg_data_i;
  wire jtag_mem_we_o;
  wire [31:0] jtag_mem_addr_o;    
  wire [31:0] jtag_mem_data_i;
  wire [31:0] jtag_mem_data_o;
  wire jtag_debug_req;

  // tinyriscv port
  wire int_flag;
  wire rib_hold_flag_o;

  wire [31:0] ibus_addr;
  wire [31:0] instruction;
  wire [31:0] core_loadstore_addr;
  wire [31:0] core_loadstore_data_in;
  wire [31:0] core_loadstore_data_out;
  wire core_loadstore_ce;
  wire core_loadstore_we;
  wire [3:0] core_loadstore_wmask;

  wire hx_valid;
  wire soft_rst;

  core m_core(
    .clk(core_clk),
    .rst_n(reset_n),
    .core_loadstore_addr(core_loadstore_addr),
    .core_loadstore_data_in(core_loadstore_data_in),
    .core_loadstore_data_out(core_loadstore_data_out),
    .core_loadstore_ce(core_loadstore_ce),
    .core_loadstore_we(core_loadstore_we),
    .core_loadstore_wmask(core_loadstore_wmask),

    .ibus_addr(ibus_addr),
    .instruction(instruction),

    .halt_req_i(jtag_halt_req_o),

    .hx_valid(hx_valid),
    .soft_rst(soft_rst),
    .core_ex_trap_valid(int_flag),
    .core_ex_trap_ready()
 );


  // jtag模块例化
  jtag_top #(
    .DMI_ADDR_BITS(6),
    .DMI_DATA_BITS(32),
    .DMI_OP_BITS(2)
  ) u_jtag_top(
    .clk(clk_1MHz),
    .jtag_rst_n(jtag_reset_n),
    .jtag_pin_TCK(jtag_TCK),
    .jtag_pin_TMS(jtag_TMS),
    .jtag_pin_TDI(jtag_TDI),
    .jtag_pin_TDO(jtag_TDO),
    .reg_we_o(jtag_reg_we_o),
    .reg_addr_o(jtag_reg_addr_o),
    .reg_wdata_o(jtag_reg_data_o),
    .reg_rdata_i(32'b0),
    .mem_we_o(jtag_mem_we_o),
    .mem_addr_o(jtag_mem_addr_o),
    .mem_wdata_o(jtag_mem_data_o),
    .mem_rdata_i(jtag_mem_data_i),
    .op_req_o(jtag_debug_req),
    .halt_req_o(jtag_halt_req_o),
    .reset_req_o(jtag_reset_req_o)
  );

//Memory part

//rom address in bytes = [0x0???0000-0x0???ffff]: 64kBytes
//ram address in bytes  = [0x2???0000-0x2???3fff]: 16kBytes
//peripheral address    = [0x1???0000-0x1???3fff]: 16kBytes



  //bus mux

  wire[31:0] d0_addr_o, d1_addr_o, d2_addr_o;
  wire[31:0] d0_data_o, d1_data_o, d2_data_o;
  wire[31:0] d0_data_i, d1_data_i, d2_data_i;
  wire[3:0] d2_wmask_o;

//  mux_2x3 u_mux(
  mux_wmask_2x3 u_mux(
    // host 0 interface
    .h0_addr_i(jtag_mem_addr_o),
    .h0_data_i(jtag_mem_data_o),
    .h0_data_o(jtag_mem_data_i),
    .h0_req_i(jtag_debug_req),
    .h0_we_i(jtag_mem_we_o),

    // host 1 interface: connect to core's load-store bus sub2
    .h1_addr_i(core_loadstore_addr),
    .h1_data_i(core_loadstore_data_out),
    .h1_data_o(core_loadstore_data_in),
    .h1_req_i(core_loadstore_ce),
    .h1_we_i(core_loadstore_we),
    .h1_wmask_i(core_loadstore_wmask),

    // device 0 interface: to rom
    .d0_addr_o(d0_addr_o),
    .d0_data_o(d0_data_o),
    .d0_data_i(d0_data_i),
    .d0_we_o(d0_we_o),
    .d0_ce_o(d0_ce_o),

    // device 1 interface: to peripheral
    .d1_addr_o(d1_addr_o),
    .d1_data_o(d1_data_o),
    .d1_data_i(d1_data_i),
    .d1_we_o(d1_we_o),
    .d1_ce_o(d1_ce_o),

    // device 2 interface: to ram
    .d2_addr_o(d2_addr_o),
    .d2_data_o(d2_data_o),
    .d2_data_i(d2_data_i),
    .d2_we_o(d2_we_o),
    .d2_wmask_o(d2_wmask_o),
    .d2_ce_o(d2_ce_o),

    //core hold flag
    .h1_hold_flag_o(rib_hold_flag_o)
//        .h1_hold_flag_o()
  );

  // rom模块例化
  Gowin_DPB_32K I_ROM(
    .douta(d0_data_i), //output [31:0] douta
    .doutb(instruction), //output [31:0] doutb
//    .clka(clk_108MHz), //input clka
    .clka(~core_clk), //input clka
    .ocea(1'b1), //input ocea
    .cea(d0_ce_o), //input cea
    .reseta(~jtag_reset_n), //input reseta
    .wrea(d0_we_o), //input wrea
//    .clkb(clk_108MHz), //input clkb
    .clkb(~core_clk), //input clkb
    .oceb(1'b1), //input oceb
    .ceb(1'b1), //input ceb
    .resetb(~reset_n), //input resetb
    .wreb(1'b0), //input wreb
    .ada(d0_addr_o[14:2]), //input [12:0] ada
    .dina(d0_data_o), //input [31:0] dina
    .adb(ibus_addr[14:2]), //input [12:0] adb
    .dinb(32'b0) //input [31:0] dinb
  );


sram D_RAM (
//    .clk              (clk_108MHz),
    .clk              (~core_clk),
    .rst_n            (reset_n),
    .sram_icb_cmd_valid (d2_ce_o),
    .sram_icb_cmd_ready (),
    .sram_icb_cmd_addr  (d2_addr_o ),
    .sram_icb_cmd_read  (~d2_we_o ),
    .sram_icb_cmd_wdata (d2_data_o),
//    .sram_icb_cmd_wmask (4'b1111),
    .sram_icb_cmd_wmask (d2_wmask_o),
    .sram_icb_rsp_valid (),
    .sram_icb_rsp_ready (1'b1),
    .sram_icb_rsp_err   (  ),
    .sram_icb_rsp_rdata (d2_data_i)
);


    //peripherals
    wire [5:0] peri_led;
    wire peri_txd;    

    peripheral m_peripheral(
        .clk(~core_clk),
        .clk_1MHz(clk_1MHz),
        .reset_n(reset_n),
        .button(3'b111),
        .led(peri_led),
        .rxd(uart0_rxd),
        .txd(uart0_txd),
        //
        .ce(d1_ce_o),
        .wre(d1_we_o),
        .addr(d1_addr_o[13:2]),
        .data_in(d1_data_o),
        .data_out(d1_data_i),
        //
        .int_flag(int_flag)
    );


    //output
    assign led = peri_led; 

endmodule